﻿using HslCommunication;
using HslCommunication.ModBus;
using Sunny.UI;
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using ConfigHelper = Modbus_Weigh.Helper.ConfigHelper;

namespace Modbus_Weigh
{
    public partial class Form1 : UIForm
    {
        private ModbusRtu _modbusRtu;
        private CancellationTokenSource _ctsCollect;
        private CancellationTokenSource _ctsMock;
        // 是否开始采集
        private bool _isCollect = false;
        // 阻塞队列最大容量为500
        private BlockingCollection<short[]> _collection = new BlockingCollection<short[]>(500);

        // 保存btnMock的原始颜色以便恢复
        private System.Drawing.Color originalColor;

        // 保存btnMock的按钮悬停颜色以便恢复
        private System.Drawing.Color fillHoverColor;

        // 保存btnMock的按钮按下颜色以便恢复
        private System.Drawing.Color fillPressColor;

      

        public Form1()
        {
            InitializeComponent();
            InitConfig();
            InitModbus();
            InitUiRefresh();

            // 初始化原始颜色
            originalColor = btnMock.FillColor;
            fillHoverColor = btnMock.FillHoverColor;
            fillPressColor = btnMock.FillPressColor;
        }

        private void InitUiRefresh()
        {
            Task.Run(async () =>
            {
                while (true)
                {
                    _collection.TryTake(out var data);

                    if (data != null)
                    {
                        // 做一系列数据更新到界面上的处理
                        Invoke(new Action(() =>
                        {
                            if (data.Length > 8)
                            {
                                // 重量1
                                ucMeterWeight1.Value = data[0];
                                // 重量2
                                ucMeterWeight2.Value = data[1];
                                // 刷新界面上的缺料方向
                                ucArrowLoss.Direction = (data[7] == 0 ? HZH_Controls.Controls.ArrowDirection.Left : HZH_Controls.Controls.ArrowDirection.Right);
                                // 刷新界面温度计(卸料百分比)
                                ucThermometer1.Value = data[8];
                                // 刷新界面温度计(分度)
                                ucThermometer2.Value = data[3];
                            }

                        }));
                    }

                    await Task.Delay(10);
                }
            });
        }

        private void InitConfig()
        {
            // 读取配置
            ConfigHelper.Current.Load();
        }

        private void InitModbus()
        {
            _modbusRtu = new ModbusRtu();
            _modbusRtu.SerialPortInni(sp =>
            {
                sp.PortName = ConfigHelper.Current.PortName;
                sp.BaudRate = ConfigHelper.Current.BaudRate;
                sp.DataBits = ConfigHelper.Current.DataBits;
                sp.StopBits = ConfigHelper.Current.StopBits;
                sp.Parity = ConfigHelper.Current.Parity;
                sp.RtsEnable = ConfigHelper.Current.RtsEnable;
            });

            _modbusRtu.ReceiveTimeOut = ConfigHelper.Current.ReceiveTimeOut;
            _modbusRtu.AddressStartWithZero = ConfigHelper.Current.AddressStartWithZero;
            _modbusRtu.DataFormat = ConfigHelper.Current.DataFormat;
            _modbusRtu.Station = ConfigHelper.Current.Station;
            _modbusRtu.Crc16CheckEnable = ConfigHelper.Current.Crc16CheckEnable;
        }

        /// <summary>
        /// 连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                var result = _modbusRtu.Open();
                if (result.IsSuccess)
                {
                    UIMessageBox.Show("称重设备PSD900 连接成功!", "设备状态");
                }
                else
                {
                    UIMessageBox.Show(result.Message);
                }
            }
            catch (Exception ex)
            {
                UIMessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 采集数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCollect_Click(object sender, EventArgs e)
        {
            if (_modbusRtu == null && !_modbusRtu.IsOpen())
            {
                UIMessageBox.Show("请先连接称重设备");
                return;
            }

            if (_isCollect)
            {
                btnCollect.Text = "开始采集";
                // 取消采集线程
                _ctsCollect?.Cancel();
            }
            else
            {
                btnCollect.Text = "停止采集";

                _ctsCollect = new CancellationTokenSource();
                Task.Run(async () =>
                {
                    while (!_ctsCollect.IsCancellationRequested)
                    {
                        try
                        {
                            // 地址:1-9,下标0-8
                            OperateResult<short[]> result = await _modbusRtu.ReadInt16Async("1", 9);

                            if (result.IsSuccess)
                            {
                                if (!_collection.TryAdd(result.Content))
                                {
                                    // 数据满了
                                    _collection.TryTake(out var data);
                                }

                                await Task.Delay(100);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex);
                        }
                    }
                }, _ctsCollect.Token);
            }

            _isCollect = !_isCollect;
        }

        /// <summary>
        /// 模拟数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnMock_Click(object sender, EventArgs e)
        {
            if (_modbusRtu == null && !_modbusRtu.IsOpen())
            {
                btnCollect.BackColor = System.Drawing.Color.Green;
                MessageBox.Show("请先连接称重设备");
                return;
            }

            // 若已有任务运行(_ctsCollect未取消),则停止
            if (_ctsMock != null && !_ctsMock.IsCancellationRequested)
            {
                _ctsMock?.Cancel(); // 发送取消信号
                //任务结束后清理(释放资源，置空引用)
                _ctsMock.Dispose();
                _ctsMock = null;
                btnMock.Text = "开启模拟数据";
                btnMock.FillColor = originalColor;
                btnMock.FillHoverColor = fillHoverColor;
                btnMock.FillPressColor = fillPressColor;
                return;
            }

            // 启动新任务:初始化_ctsCollect,获取令牌
            _ctsMock = new CancellationTokenSource();
            btnMock.Text = "停止模拟数据";
            btnMock.FillColor = System.Drawing.Color.Red;
            btnMock.FillHoverColor= System.Drawing.Color.Red;
            btnMock.FillPressColor = System.Drawing.Color.Red;
            Task.Run(async () =>
            {
                while (_ctsMock != null && !_ctsMock.IsCancellationRequested)
                {
                    try
                    {
                        var random = new Random();
                        // 随机系数
                        var coefficient = (short)random.Next(1, 50);
                        //卸料方向只能是0和1(这里随机数范围是0,2,所能得到值只能是0和1)
                        var loss = (short)random.Next(0, 2);
                        // 卸料百分比
                        var percent = (short)random.Next(1, 45);

                        short[] data = new short[9]
                        {
                            (short)(coefficient),
                            (short)(coefficient+2),
                            (short)(coefficient+2),
                            (short)(percent+2),
                            (short)(percent*2),
                            (short)(coefficient+2),
                            (short)(coefficient+2),
                            (short)(loss),
                            (short)(percent),
                        };

                        var result = await _modbusRtu.WriteAsync("1", data);

                        await Task.Delay(100);
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine(exception);
                    }
                }
            }, _ctsMock.Token);
        }
    }
}
